#pragma once
#include <iostream>
#include <vector>
#include <pthread.h>
#include <semaphore.h>

template<class T>
class RingQueue
{
public:
  RingQueue(int capacity = 5)
    :_capacity(capacity)
     ,_rq(capacity)
     ,_c_index(0)
     ,_p_index(0)
  {
    sem_init(&_blank_sem, 0, _capacity);
    sem_init(&_data_sem, 0, 0);
  }
  void GetData(T& data)
  {
    // consumer申请数据资源
    P(_data_sem);
    data = _rq[_c_index];
    _c_index = (_c_index + 1) % _capacity;
    // consumer释放格子资源
    V(_blank_sem);
  }
  void PutData(const T& data)
  {
    // productor申请格子资源
    P(_blank_sem);
    _rq[_p_index] = data;
    _p_index = (_p_index + 1) % _capacity;
    // productor释放数据资源
    V(_data_sem);
  }
  ~RingQueue()
  {
    sem_destroy(&_blank_sem);
    sem_destroy(&_data_sem);
  }
private:
  void P(sem_t& sem)
  {
    sem_wait(&sem);
  }
  void V(sem_t& sem)
  {
    sem_post(&sem);
  }
private:
  std::vector<T> _rq;
  size_t   _capacity;
  sem_t       _blank_sem;
  sem_t       _data_sem;
  int       _c_index;
  int       _p_index;
};
